package com.bruce.exec.utils;

import cn.hutool.core.util.RuntimeUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;

/**
 * @author xin.ding
 * @date 2021/4/16 20:42
 */
@Slf4j
public class UnixProcess implements ProcessHandler {

    @Override
    public String getProcessId(Process process) {
        if (process == null) {
            log.error("进程不存在");
            return null;
        }
        Class<?> clazz = process.getClass();
        try {
            if (clazz.getName().equals("java.lang.UNIXProcess")) {
                Field pidField = clazz.getDeclaredField("pid");
                pidField.setAccessible(true);
                Object value = pidField.get(process);
                if (value instanceof Integer) {
                    return ((Integer) value).toString();
                }
            }
        } catch (SecurityException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException sx) {
            sx.printStackTrace();
        }
        return null;
    }

    @Override
    public String getOtherPid(String pName) {
        Runtime runtime = Runtime.getRuntime();
        try {
            Process pro = runtime.exec("ps -ef");
            BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream(), StandardCharsets.UTF_8));
            String str = "";
            while ((str = br.readLine()) != null) {
                if (str.trim().equals("") || !str.contains(pName)) {
                    continue;
                }
                br.close();
                String subStr = str.substring(str.indexOf(" ")).trim();
                return subStr.substring(0, subStr.indexOf(" "));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean killProcess(Process process) {
        if (process == null) {
            return true;
        }
        Process killPro = process.destroyForcibly();
        return !killPro.isAlive();
    }

    @Override
    public boolean killProcess(String pid) {
        boolean killed = false;
        Runtime runtime = Runtime.getRuntime();
        try {
            Process pro = runtime.exec(new String[]{"kill", "-9", pid});
            try {
                int code = pro.waitFor();
                if (code == 0) {
                    killed = true;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return killed;
    }

    /**
     * 进程是否存活
     *
     * @param pid 进程Pid
     * @return bool
     */
    @Override
    public boolean isActivePid(String pid) {
        try {
            Process process = RuntimeUtil.exec("kill", "-0", pid);
            byte[] b = new byte[200];
            process.getInputStream().read(b);
            String str = new String(b, StandardCharsets.UTF_8);
            if (str.trim().equals("") || str.trim().equals("0")) {
                return true;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return false;
    }

}
